package com.dashuai.modbus.core.slave;

import com.dashuai.modbus.config.CoilProperties;
import com.dashuai.modbus.config.InputProperties;
import com.dashuai.modbus.config.ProcessImageProperties;
import com.dashuai.modbus.config.RegisterProperties;
import com.serotonin.modbus4j.BasicProcessImage;
import com.serotonin.modbus4j.ip.tcp.TcpSlave;
import lombok.extern.slf4j.Slf4j;

import java.util.List;

/**
 * <p>
 *
 * </p>
 *
 * @author QM
 * @date 2024/8/21
 */
@Slf4j
public class ModbusTCPSlave extends TcpSlave implements Runnable {



    @Override
    public void run() {

        try {
            // 这个方法内部会阻塞
            this.start();
        } catch (Exception e) {
            log.error("modbus tcp slave initialization failure", e);
        }
    }


    public ModbusTCPSlave(int port, boolean encapsulated, List<ProcessImageProperties> processImageList) {

        super(port, encapsulated);
        initProcessImage(processImageList);
    }


    private void initProcessImage(List<ProcessImageProperties> processImageList) {

        if (processImageList != null && !processImageList.isEmpty()) {
            for (ProcessImageProperties properties : processImageList) {

                final BasicProcessImage processImage = getBasicProcessImage(properties);

                // 设置保持寄存器
                final RegisterProperties holdingRegister = properties.getHoldingRegister();
                if (holdingRegister != null) {
                    final int holdingStartOffset = holdingRegister.getStartOffset();
                    final int holdingCount = holdingRegister.getCount();
                    processImage.setHoldingRegister(holdingStartOffset, new short[holdingCount]);
                }

                // 设置输入寄存器
                final RegisterProperties inputRegister = properties.getInputRegister();
                if (inputRegister != null) {
                    final int inputStartOffset = inputRegister.getStartOffset();
                    final int inputCount = inputRegister.getCount();
                    processImage.setInputRegister(inputStartOffset, new short[inputCount]);
                }

                // 将 processImage 添加到从设备
                this.addProcessImage(processImage);
            }
        }
    }

    private static BasicProcessImage getBasicProcessImage(ProcessImageProperties properties) {
        final int slaveId = properties.getSlaveId();

        BasicProcessImage processImage = new BasicProcessImage(slaveId);

        // 设置线圈
        final List<CoilProperties> coilList = properties.getCoils();
        if (coilList != null && !coilList.isEmpty()) {
            for (CoilProperties coilProperties : coilList) {

                final int offset = coilProperties.getOffset();
                final boolean value = coilProperties.isValue();
                processImage.setCoil(offset, value);
            }
        }

        // 设置输入
        final List<InputProperties> inputList = properties.getInputs();
        if (inputList != null && !inputList.isEmpty()) {
            for (InputProperties inputProperties : inputList) {

                final int offset = inputProperties.getOffset();
                final boolean value = inputProperties.isValue();
                processImage.setInput(offset, value);
            }
        }

        return processImage;
    }

}
